package net.daum.mail.util;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.internet.ContentType;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.internet.ParseException;

import org.apache.commons.lang.StringUtils;

import com.sun.mail.imap.IMAPBodyPart;
import com.sun.mail.imap.IMAPNestedMessage;

public class MimeUtils {

	public static String getPrimaryType(String contentType) {
		String primaryType = null;
		try {
			ContentType type = new ContentType(contentType);
			primaryType = type.getPrimaryType();
		} catch (ParseException e) {
			// don't care
			primaryType = contentType;
		}
		return primaryType;
	}
	
	public static String getBaseType(String contentType) {
		String baseType = null;
		try {
			ContentType type = new ContentType(contentType);
			baseType = type.getBaseType();
		} catch (ParseException e) {
			// don't care
			baseType = contentType;
		}
		return baseType;
	}
	
	public static String getSubType(String contentType) {
		String subType = null;
		try {
			ContentType type = new ContentType(contentType);
			subType = type.getSubType();
		} catch (ParseException e) {
			// don't care
			subType = contentType;
		}
		return subType;
	}

	public static String getParameter(String contentType, String parameterName) {
		String paremeter = null;
		try {
			ContentType type = new ContentType(contentType);
			paremeter = type.getParameter(parameterName);
		} catch (ParseException e) {
			// don't care
		}
		return paremeter;
	}
	
	public static String getFileName(Part part) throws MessagingException {
		String filename = null;
		String mimeFilename;
		if (part instanceof IMAPNestedMessage) {
			mimeFilename = ((IMAPNestedMessage) part).getSubject() + ".eml";
		} else {
			mimeFilename = part.getFileName();
		}
		
		if (StringUtils.isEmpty(mimeFilename)) {
			mimeFilename = getParameter(part.getContentType(), "name");
		}

		if (StringUtils.isEmpty(mimeFilename)) {
			filename = "NONAME";
		} else {
			try {
				// MimeUtility의 decodeText는 ?==? 공백없이 이어진 것을 처리하지 못한다. 
				mimeFilename = StringUtils.replace(mimeFilename, "?==?", "?= =?");
				
				filename = MimeUtility.decodeText(mimeFilename);
			} catch (UnsupportedEncodingException e) {
				filename = part.getFileName();
			}
		}
		
		return filename;
	}

	/**
	 * contentId가 <cid> 형태로 header에 들어가는데 실제 사용은 cid:cid 형태로 사용한다.
	 * 따라서 <, >는 없애고 가져온다.
	 * @param part
	 * @return contentId
	 * @throws MessagingException 
	 */
	public static String getContentId(Part part) throws MessagingException {
		if (part instanceof IMAPBodyPart) {
			String rawContentId = ((IMAPBodyPart) part).getContentID();
			String contentId = "";
			if (StringUtils.isNotEmpty(rawContentId)) {
				Matcher matcher = Pattern.compile("<(.*)>").matcher(rawContentId);
				if (matcher.find()) {
					contentId = matcher.group(1);
				} else {
					contentId = rawContentId;
				}
			}
			return contentId;	
		} else {
			return null;
		}
	}
	
	public static String getSectionId(Part part) {
		if (part instanceof IMAPBodyPart) {
			return ((IMAPBodyPart) part).getSectionId();
		} else {
			return null;
		}
	}
	

	public static boolean isMultipartReport(MimeMultipart content) {
		try {
			if (content.getCount() == 3
					&& StringUtils.equalsIgnoreCase("delivery-status", MimeUtils.getSubType(content.getBodyPart(1).getContentType()))) {
				return true;
			}
		} catch(Exception e) {
			// ignore
		}
		return false;
	}

	public static Map<String, String> makeHeadersMapFromBody(String statusBody) {
		Map<String, String> headers = new HashMap<String, String>();
		Matcher matcher = Pattern.compile("([^:\r\n]+):([^\r\n]+)").matcher(statusBody);
		while(matcher.find()) {
			String name = matcher.group(1);
			String value = matcher.group(2);
			headers.put(name, value);
		}
		return headers;
	}

	public static String getMessageReportReason(String status) {
		Matcher matcher = Pattern.compile("([0-9])\\.([0-9])\\.([0-9])").matcher(status);
		int statusClass = -1;
		int statusSubject = -1;
		int statusDetail = -1;
		if (matcher.find()) {
			statusClass = Integer.parseInt(matcher.group(1));
			statusSubject = Integer.parseInt(matcher.group(2));
			statusDetail = Integer.parseInt(matcher.group(3));
		}
		
		String content = null;
		if (statusClass == 5) {
			if (statusSubject == 0) {
				content = "받는 이의 메일주소가 존재하지 않거나 오랫동안 사용하지 않아서 휴면상태이거나 메일용량이 꽉 찼을 수 있습니다.";
			} else if (statusSubject == 1) {
				if (statusDetail == 1) {
					content = "받는이의 메일주소가 존재하지 않거나 오랫동안 사용하지 않아서 휴면상태 입니다.";
				} else if (statusDetail == 2) {
					content = "받는이의 메일주소에 해당되는 메일서버가 존재하지 않습니다.";
				} else if (statusDetail == 3) {
					content = "받는이의 메일주소 형식이 문법에 맞지 않습니다.";
				} else {
					content = "받는이의 메일주소에 문제가 있습니다.";
				}
			} else if (statusSubject == 2) {
				if (statusDetail == 1) {
					content = "받는이가 속한 메일서버를 잠시 점검중입니다.";
				} else if (statusDetail == 2) {
					content = "받는이의 편지함 용량이 꽉 찼습니다.";
				} else if (statusDetail == 3) {
					content = "발송하신 편지가 제한된 크기를 초과 하였습니다.";
				} else {
					content = "받는 이의 편지함에 문제가 있습니다.";
				}
			} else if (statusSubject == 3) {
				if (statusDetail == 2) {
					content = "받는이가 속한 메일서버가 제대로 동작하지 않습니다.";
				} else if (statusDetail == 4) {
					content = "발송하신 편지의 크기가 너무커서 받는이가 속한 메일서버에서 수신을 거부하였습니다.";
				} else {
					content = "받는이가 속한 메일서버가 제대로 동작하지 않습니다.";
				}
			} else if (statusSubject == 4) {
				content = "네트워크 문제로 메일을 전송할 수 없습니다.";
			} else if (statusSubject == 5) {
				if (statusDetail == 3) {
					content = "받는이의 인원수가 제한을 초과하였습니다.";
				} else if (statusDetail == 4) {
					content = "받는이의 메일주소 형식이 문법에 맞지 않습니다.";
				} else {
					content = "메일 전송 규약과 관련된 에러가 발생하였습니다.";
				}
			} else if (statusSubject == 6) {
				content = "메일전송에 문제가 있습니다.";
			} else if (statusSubject == 7) {
				if (statusDetail == 1) {
					content = "아래의 세가지 경우 중 하나에 해당됩니다.<ol><li>받는이가 회원님의 메일주소를 수신거부 하였습니다.</li><li>받는이가 속한 메일서버가 회원님의 메일주소를 수신거부 하였습니다.</li><li>받는이가 속한 메일서버가 Daum 메일에서 발송된 메일에 대해 수신거부 하였습니다.</li></ol>";
				} else {
					content = "메일전송에 문제가 있습니다.";
				}
			}
		}
		return content;
	}

	public static String getMessageReportHelpMessage(String status) {
		Matcher matcher = Pattern.compile("([0-9])\\.([0-9])\\.([0-9])").matcher(status);
		int statusClass = -1;
		int statusSubject = -1;
		int statusDetail = -1;
		if (matcher.find()) {
			statusClass = Integer.parseInt(matcher.group(1));
			statusSubject = Integer.parseInt(matcher.group(2));
			statusDetail = Integer.parseInt(matcher.group(3));
		}
		
		String content = null;
		if (statusClass == 5) {
			if (statusSubject == 0) {
				content = "- 받는 이의 메일주소가 존재하지 않는 경우: 정확한 메일주소를 다시 확인하세요.<br>- 받는 이의 메일주소가 휴면상태인 경우: 받는 이가 오랫동안 해당 메일주소를 사용하지 않고 있습니다. 혹시 다른 메일주소를 사용하지는 않는지 확인해보세요.<br>- 메일용량이 꽉 찬 경우: 받는 이가 자신의 편지함을 정리(휴지통비우기) 하셔야만 메일 전송이 가능합니다.";
			} else if (statusSubject == 1) {
				if (statusDetail == 1) {
					content = "받는이의 정확한 메일주소를 다시 한번 확인하셔서 발송해보세요.";
				} else if (statusDetail == 2) {
					content = "받는이의 메일주소에서 도메인부분(@ 오른쪽 부분)이 맞는지 다시 한번 확인하셔서 발송해보세요.";
				} else if (statusDetail == 3) {
					content = "메일주소는 id@daum.net 또는 \"이름\" &lt;id@daum.net&gt; 과 같은 형식이어야 하며, Daum 주소록에 등록된 이름을 사용하실 때는 이름앞에 #을 붙여주셔야 합니다.(예: #주소록이름)<br>여러명에게 보낼때는 콤마(,)로 구분하셔야 합니다";
				} else {
					content = "받는 이의 정확한 메일 주소를 다시 한번 확인하셔서 발송해보세요.";
				}
			} else if (statusSubject == 2) {
				if (statusDetail == 1) {
					content = "잠시 후에 다시 발송하시기 바랍니다.";
				} else if (statusDetail == 2) {
					content = "받는이에게 편지함정리(휴지통 비우기)를 요청하신 후 다시 발송해보세요.";
				} else if (statusDetail == 3) {
					content = "편지의 크기를 줄이시거나 여러 통으로 나누어서 보내세요";
				} else {
					content = "받는 이의 편지함 문제가 해결된 이후에 다시 발송하셔야 합니다.";
				}
			} else if (statusSubject == 3) {
				if (statusDetail == 2) {
					content = "받는이에게 다른 메일주소가 있으면 그쪽으로 메일을 발송하세요. 그렇지 않으면 받는이 쪽 메일서버 담당자(서비스 담당자)에게 문의하시기 바랍니다.";
				} else if (statusDetail == 4) {
					content = "편지의 크기를 줄이시거나 여러 통으로 나누어서 보내세요. 첨부파일이 있는 경우 파일을 여러개로 나누어서 보내세요.";
				} else {
					content = "받는이가 속한 메일서버 담당자(서비스 담당자)에게 문의하시기 바랍니다.";
				}
			} else if (statusSubject == 4) {
				content = "아래 부분을 복사하셔서 Daum 메일 고객센터에 문의메일을 보내주세요.";
			} else if (statusSubject == 5) {
				if (statusDetail == 3) {
					content = "편지를 여러통으로 나누어서 발송하시기 바랍니다.";
				} else if (statusDetail == 4) {
					content = "메일주소는 id@daum.net 또는 \"이름\" &lt;id@daum.net&gt; 과 같은 형식이어야 하며, Daum 주소록에 등록된 이름을 사용하실 때는 이름앞에 #을 붙여주셔야 합니다.(예: #주소록이름)<br>여러명에게 보낼때는 콤마(,)로 구분하셔야 합니다.";
				} else {
					content = "아래 부분을 복사하셔서 Daum 메일 고객센터에 문의메일을 보내주세요.";
				}
			} else if (statusSubject == 6) {
				content = "아래 부분을 복사하셔서 Daum 메일 고객센터에 문의메일을 보내주세요. 저희가 확인해드리겠습니다.";
			} else if (statusSubject == 7) {
				if (statusDetail == 1) {
					content = "<ol><li>인 경우: 받는이에게 회원님의 메일주소를 수신거부 목록에서 지워줄 것을 요청하셔야 합니다.</li><li>인 경우: 받는이가 속한 메일서버의 서비스담당자에게 회원님의 메일주소를 수신거부 목록에서 지워줄 것을 요청하셔야 합니다.</li><li>인 경우: 아래 회색부분을 복사하셔서 고객센터에 문의메일을 보내주세요.</li></ol>";
				} else {
					content = "아래 부분을 복사하셔서 Daum 메일 고객센터에 문의메일을 보내주세요. 저희가 확인해드리겠습니다.";
				}
			}
		}
		return content;
	}

	public static String getFirstHeader(Part part, String headerName) throws MessagingException {
		String[] headers = part.getHeader(headerName);
		if (headers != null && headers.length > 0) {
			return headers[0];
		}
		return null;
	}

	public static String getContentType(Part part) throws MessagingException {
		if (part instanceof IMAPNestedMessage) {
			return "message/rfc822";
		} else {
			return MimeUtils.getBaseType(part.getContentType());
		}
	}
}
